package bg.btanev.eightyfour.client.presenter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import bg.btanev.eightyfour.client.presenter.ProfileEventsSearchPresenter.ProfileEventsSearchListener;
import bg.btanev.eightyfour.client.presenter.listener.OpenPanelListener;
import bg.btanev.eightyfour.client.presenter.listener.TargetActionMenuOpenListener;
import bg.btanev.eightyfour.client.service.GWTCommandServiceAsync;
import bg.btanev.eightyfour.client.view.PersonView;
import bg.btanev.eightyfour.client.view.ProfileEventListElementView;
import bg.btanev.eightyfour.client.view.ProfileEventsSearchView;
import bg.btanev.eightyfour.client.view.ProfilesView;
import bg.btanev.eightyfour.client.view.SearchTargetView;
import bg.btanev.eightyfour.client.view.StatsListView;
import bg.btanev.eightyfour.client.view.TargetListView;
import bg.btanev.eightyfour.shared.command.CommandResult;
import bg.btanev.eightyfour.shared.command.person.UpdatePersonCommand;
import bg.btanev.eightyfour.shared.command.person.UpdatePersonInput;
import bg.btanev.eightyfour.shared.command.profileevent.FindProfileEventsCommand;
import bg.btanev.eightyfour.shared.command.profileevent.FindProfileEventsInput;
import bg.btanev.eightyfour.shared.command.target.CreateTargetCommand;
import bg.btanev.eightyfour.shared.command.target.CreateTargetInput;
import bg.btanev.eightyfour.shared.command.target.FindTargetsCommand;
import bg.btanev.eightyfour.shared.command.target.FindTargetsInput;
import bg.btanev.eightyfour.shared.dto.TargetDto;
import bg.btanev.eightyfour.shared.dto.person.PersonDto;
import bg.btanev.eightyfour.shared.dto.profile.ProfileEventDto;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.HasBeforeSelectionHandlers;
import com.google.gwt.event.logical.shared.HasSelectionHandlers;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;

/**
 *
 * @author B.Tanev
 *
 */
public class TargetTabPresenter extends BasePresenter {

	private static final String MENU_ADD = "Add";
	private static final String MENU_PERSON = "Person";
	private static final String MENU_PROFILES = "Profiles";
	private static final String MENU_SEARCH = "Search";
	private static final String MENU_STATISTICS = "Statistics";

	private static final String[] MENUS = new String[] { MENU_PERSON, MENU_PROFILES, MENU_SEARCH, MENU_STATISTICS };

	private static final String[] GLOBAL_TARGET_MENU = new String[] { MENU_ADD, MENU_SEARCH };

	public static interface TargetTabDisplay extends Display {
		HasBeforeSelectionHandlers<Integer> getBeforeSelectionActionMenuHandlers();

		HasSelectionHandlers<Integer> getSelectionActionMenuHandlers();

		HasWidgets getActionDataContainer();

		HasWidgets getDataContainer();

		void addActionMenus(String[] actionMenus);
	}

	private final TargetListView targetListView;
	private final Map<Long, HasWidgets> targetProfileEventsContainer = new HashMap<Long, HasWidgets>();

	@SuppressWarnings("unchecked")
	public TargetTabPresenter(final TargetTabDisplay view, final HandlerManager eventBus,
			final GWTCommandServiceAsync rpcService) {

		super(view, eventBus, rpcService);

		this.targetListView = new TargetListView();
		this.targetListView.setTargetMenus(MENUS);
		this.targetListView.setTargetMenuListener(new TargetActionMenuOpenListener() {
			@Override
			public void onOpen(String actionMenu, TargetDto target, HasWidgets container) {
				Presenter presenter = null;
				if (MENU_PERSON.equals(actionMenu)) {
					presenter = ProfileActionMenuClicked(target);
				} else if (MENU_PROFILES.equals(actionMenu)) {
					presenter = new ProfilesPresenter(rpcService, new ProfilesView(), target);
				} else if (MENU_SEARCH.equals(actionMenu)) {
					ProfileEventsSearchPresenter profileEventsSearchPresenter = new ProfileEventsSearchPresenter(
							rpcService, new ProfileEventsSearchView(), target);
					profileEventsSearchPresenter.addSearchListener(new ProfileEventsSearchListener() {
						@Override
						public void onNewSearchRequest(FindProfileEventsInput input) {
							if (input == null || input.getTarget() == null) {
								return;
							}

							TargetDto searchTarget = input.getTarget();
							Long targetId = searchTarget.getId();
							if (targetId == null || targetId.longValue() <= 0) {
								return;
							}

							HasWidgets profileEventsContainer = targetProfileEventsContainer.get(targetId);
							if (profileEventsContainer != null) {
								UpdateTargetProfileEventsView(profileEventsContainer, input);
							}
						}
					});

					presenter = profileEventsSearchPresenter;
				} else if (MENU_STATISTICS.equals(actionMenu)) {
					presenter = new StatsListPresenter(rpcService, new StatsListView(), target);
				}

				if (presenter != null) {
					presenter.go(container);
				}
			}
		});
		this.targetListView.addOpenPanelListener(new OpenPanelListener() {
			@Override
			public void onOpen(final HasWidgets dataPanel, final TargetDto target) {
				if (target == null || target.getId() == null || target.getId().longValue() <= 0) {
					return;
				}

				targetProfileEventsContainer.put(target.getId(), dataPanel);

				FindProfileEventsInput input = new FindProfileEventsInput();
				input.setTarget(target);

				UpdateTargetProfileEventsView(dataPanel, input);
			}
		});
	}

	@SuppressWarnings("unchecked")
	private void UpdateTargetProfileEventsView(final HasWidgets dataPanel, final FindProfileEventsInput input) {
		dataPanel.clear();
		dataPanel.add(new Label("No data"));

		if (input != null) {
			dataPanel.clear();
			dataPanel.add(new Label("Loading..."));

			FindProfileEventsCommand command = new FindProfileEventsCommand();
			command.setInput(input);
			rpcService.executeCommand(command,
					new AsyncCallback<CommandResult<FindProfileEventsInput, ArrayList<ProfileEventDto>>>() {
						@Override
						public void onFailure(Throwable caught) {
							dataPanel.clear();
							dataPanel.add(new Label("Error..."));
						}

						@Override
						public void onSuccess(CommandResult<FindProfileEventsInput, ArrayList<ProfileEventDto>> result) {

							dataPanel.clear();
							if (result == null) {
								return;
							}
							ArrayList<? extends ProfileEventDto> profileEvents = result.getResult();
							if (profileEvents == null || profileEvents.size() == 0) {
								return;
							}

							for (int i = 0; i < profileEvents.size(); i++) {
								ProfileEventDto profileEvent = profileEvents.get(i);

								ProfileEventListElementView view = new ProfileEventListElementView();
								view.setProfileEvent(profileEvent);

								dataPanel.add(view);
							}
						}
					});
		}
	}

	private Presenter ProfileActionMenuClicked(TargetDto target) {
		Presenter presenter;
		final PersonPresenter personPresenter = new PersonPresenter(rpcService, new PersonView(), target);
		personPresenter.getSaveClickhandler().addClickHandler(new ClickHandler() {
			@SuppressWarnings("unchecked")
			@Override
			public void onClick(ClickEvent event) {
				PersonDto person = personPresenter.getPersonFromView();
				if (person == null) {
					return;
				}

				UpdatePersonCommand command = new UpdatePersonCommand();
				UpdatePersonInput input = new UpdatePersonInput();
				input.setPerson(person);
				command.setInput(input);

				rpcService.executeCommand(command, new AsyncCallback<CommandResult<UpdatePersonInput, PersonDto>>() {
					@Override
					public void onFailure(Throwable caught) {

					}

					@Override
					public void onSuccess(CommandResult<UpdatePersonInput, PersonDto> result) {
						if (result != null) {
							PersonDto person = result.getResult();
							personPresenter.getTarget().setPerson(person);
							personPresenter.setPerson(person);
						}
					}
				});
			}
		});

		presenter = personPresenter;
		return presenter;
	}

	@Override
	protected void bind() {
		final TargetTabDisplay display = getDisplay();
		display.addActionMenus(GLOBAL_TARGET_MENU);
		display.getSelectionActionMenuHandlers().addSelectionHandler(new SelectionHandler<Integer>() {
			@Override
			public void onSelection(SelectionEvent<Integer> event) {
				Integer selectedItem = event.getSelectedItem();
				if (selectedItem != null) {
					int menuPos = selectedItem.intValue();
					if (menuPos >= 0 && menuPos < GLOBAL_TARGET_MENU.length) {
						String selMenu = GLOBAL_TARGET_MENU[menuPos];
						Presenter presenter = null;
						if (MENU_ADD.equals(selMenu)) {
							final PersonPresenter personPresenter = new PersonPresenter(rpcService, new PersonView(),
									null);
							personPresenter.getSaveClickhandler().addClickHandler(new ClickHandler() {
								@SuppressWarnings("unchecked")
								@Override
								public void onClick(ClickEvent event) {
									PersonDto person = personPresenter.getPersonFromView();
									if (person == null) {
										return;
									}

									CreateTargetCommand command = new CreateTargetCommand();
									CreateTargetInput input = new CreateTargetInput();
									input.setPerson(person);
									command.setInput(input);

									rpcService.executeCommand(command,
											new AsyncCallback<CommandResult<CreateTargetInput, TargetDto>>() {

												@Override
												public void onFailure(Throwable caught) {
												}

												@Override
												public void onSuccess(CommandResult<CreateTargetInput, TargetDto> result) {
													loadTargets(null, null, null);
												}
											});
								}
							});

							presenter = personPresenter;
						} else if (MENU_SEARCH.equals(selMenu)) {
							final SearchTargetPresenter searchTargetPresenter = new SearchTargetPresenter(rpcService,
									new SearchTargetView());
							searchTargetPresenter.getSearchRequest().addClickHandler(new ClickHandler() {
								@Override
								public void onClick(ClickEvent event) {
									loadTargets(searchTargetPresenter.getEmail(), searchTargetPresenter.getFirstName(),
											searchTargetPresenter.getLastName());
								}
							});

							presenter = searchTargetPresenter;
						}

						if (presenter != null) {
							presenter.go(display.getActionDataContainer());
						}
					}
				}
			}
		});
	}

	@Override
	public void go(HasWidgets container) {
		TargetTabDisplay display = getDisplay();
		HasWidgets dataContainer = display.getDataContainer();
		dataContainer.clear();
		dataContainer.add(this.targetListView);

		loadTargets(null, null, null);

		if (container != null) {
			container.clear();
			container.add(getDisplay().asWidget());
		}
	}

	@SuppressWarnings("unchecked")
	private void loadTargets(String email, String fName, String lName) {
		FindTargetsCommand command = new FindTargetsCommand();
		FindTargetsInput input = new FindTargetsInput();

		input.setEmail(email);
		input.setFirstName(fName);
		input.setLastName(lName);

		command.setInput(input);

		rpcService.executeCommand(command, new AsyncCallback<CommandResult<FindTargetsInput, ArrayList<TargetDto>>>() {

			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(CommandResult<FindTargetsInput, ArrayList<TargetDto>> result) {
				ArrayList<TargetDto> targets = null;
				if (result != null) {
					targets = result.getResult();
				}
				targetListView.setTargets(targets);
			}
		});
	}
}
